﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using COFE.Core.Logger;

namespace COFE.Data
{
    #region Non-Generic version

    public abstract class DBEventLoggerBase<DE> : IEventLogger
        where DE : COFE.Data.Event
    {
        #region Constructor

        #endregion

        #region Methods

        public abstract void DispatchEvent(object sender, EventArgs args);            

        protected abstract IEventLog createEventArgs(DE e);        

        public IEnumerable<IEventLog> GetEventLog(string sender)
        {
            return COFEDBShared.DBOperations.ReadDatabase(
              (context) =>
              {
                  var events =
                      (from e in context.Events.OfType<DE>()
                       where e.Sender == sender
                       orderby e.Time
                       select e).ToList();

                  return (from e in events
                          select createEventArgs((DE)e)).ToList();

              });
        }

        public IEnumerable<IEventLog> GetEventLog(TimeSpan pastTime)
        {
            return GetEventLog(DateTime.UtcNow.Subtract(pastTime), DateTime.UtcNow);
        }

        public IEnumerable<IEventLog> GetEventLog(DateTime startTimeUtc, DateTime endTimeUtc)
        {
            return COFEDBShared.DBOperations.ReadDatabase(
                (context) =>
                {
                    var events = 
                        (from e in context.Events.OfType<DE>()
                         where e.Time >= startTimeUtc && e.Time <= endTimeUtc
                         orderby e.Time
                         select e).ToList();

                    return (from e in events
                            select createEventArgs((DE)e));

                });
        }

        #endregion

        #region Data

        #endregion

        #region Public Properties

        public IEventLog this[long id]
        {
            get {

                return COFEDBShared.DBOperations.ReadDatabase(
                    (context) =>
                    {                        
                          var dbEvent = (from e in context.Events.OfType<DE>().Include("Work")
                             where e.EventId == id select e).FirstOrDefault();                             

                        return dbEvent == null ? null : createEventArgs((DE)dbEvent);;

                    });
            
            }
        }

        #endregion


    }

    #endregion

    #region Generic version
    public abstract class DBEventLoggerBase<DE,EA> : DBEventLoggerBase<DE>, IEventLogger<EA>
        where DE : COFE.Data.Event
        where EA : EventArgs
    {
        public abstract void DispatchEvent(object sender, EA args);

        public new IEnumerable<IEventLog<EA>> GetEventLog(string sender)
        {
            return from l in base.GetEventLog(sender)
                   select l.ToGeneric<EA>();
        }

        public new IEnumerable<IEventLog<EA>> GetEventLog(TimeSpan pastTime)
        {
            return from l in base.GetEventLog(pastTime)
                   select l.ToGeneric<EA>();
        }

        public new IEnumerable<IEventLog<EA>> GetEventLog(DateTime startTimeUtc, DateTime endTimeUtc)
        {
            return from l in base.GetEventLog(startTimeUtc, endTimeUtc)
                   select l.ToGeneric<EA>();
        }

        public new IEventLog<EA> this[long id]
        {
            get
            {
                var baseLog = base[id];
                return baseLog == null ? null : baseLog.ToGeneric<EA>();
            }
        }
    }

    #endregion
}
